package com.dahua.messagesyncbj.config.redis;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class RedisUtil {
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public void setRedisTemplate(RedisConfig redisConfig) {
        this.redisTemplate = redisConfig.redisTemplate(redisConfig.jedisConnectionFactory(redisConfig.jedisPoolConfig()));
        redisTemplate.afterPropertiesSet();
    }

    //String
    public void setString(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public Object getString(String key) {
        return redisTemplate.opsForValue().get(key);
    }


    //List
    public void rightPush(String key, @NonNull Object var) {
        RLock lock = redissonClient.getLock(key + "lock");
        try {
            lock.lock();
            redisTemplate.opsForList().rightPush(key, var);
        } finally {
            lock.unlock();
        }
    }

    public void leftPush(String key, List<Object> list) {
        RLock lock = redissonClient.getLock(key + "lock");
        try {
            lock.lock();
            if (!list.isEmpty()) {
                redisTemplate.opsForList().leftPushAll(key, list);
            }
        } finally {
            lock.unlock();
        }
    }

    public Object leftPop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    public List<Object> leftPop(String key, int start, int end) {
        RLock lock = redissonClient.getLock(key + "lock");
        try {
            lock.lock();
            List<Object> range = redisTemplate.opsForList().range(key, start, end);
            for (int i = 0; i < listSize(key); i++) {
                redisTemplate.opsForList().leftPop(key);
            }
            return range;
        } finally {
            lock.unlock();
        }
    }

    public Long listSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    //hash
    public void setHash(String key, String field, Object var) {
        try {
            redisTemplate.opsForHash().put(key, field, var);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    public Map<Object, Object> getHash(String key) {
        try {
            return redisTemplate.opsForHash().entries(key);
        } catch (Exception e) {
            return null;
        }
    }

    public Object getHash(String key, String field) {
        Object entries = null;
        try {
            entries = redisTemplate.opsForHash().get(key, field);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return entries;
    }

    public void deleteHash(String key, String field) {
        try{
            redisTemplate.opsForHash().delete(key, field);
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }

    //锁
    public boolean tryLock(String key) {
        boolean flag = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, "lock"));
        if (flag) {
            boolean b = this.setExpireTime(key);
        }
        return flag;
    }

    public void unLock(String key) {
        this.deleteKey(key);
    }


    //其他
    public void deleteKey(String key) {
        redisTemplate.delete(key);
    }

    public boolean setExpireTime(String key) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, (int) (1200 + Math.random() * (1800 - 1200 + 1)), TimeUnit.MINUTES));
    }

    public boolean setExpireTime(String key, int ttl) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, ttl, TimeUnit.MINUTES));
    }

    public boolean setExpireTime(String key, int ttl, TimeUnit timeUnit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, ttl, timeUnit));
    }

    public Long getExpireTime(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public boolean isExist(String key) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }
}
